ident = '$Id: gcb_ui.py 109 2006-06-05 18:46:37Z trevor $'

#!/usr/bin/python2

import wx,sys
import rex, common, images, re, icon_manager
from xml.dom	 			import minidom
from xml.sax 	import saxutils


# Menu bar items
ID_GCB_CREATE	= 101
ID_GCB_EDIT		= 102
ID_GCB_DELETE	= 103
ID_GCB_CLOSE	= 104
ID_GCB_LIST		= 105
INS_LIST 		= 200
ID_RULE  		= 201
ID_SAVE			= 202
ID_CANCEL		= 203


ID_CGTIMER_TIMER	= 102


####################################################################################################
# Controls
ID_RPP				= 101
ID_FINDBY_TEXT		= 102
ID_GET_BUTTON		= 103
ID_GCB_LIST	= 104
ID_PAGER			= 105
ID_NEXT_BUTTON  	= 106
ID_PREV_BUTTON  	= 107
ID_SHOWBY			= 108
ID_GROUPS_LIST		= 109
ID_NB				= 110

ID_PUB_OPEN			= 201
ID_ISS_OPEN			= 202

ID_INSTANCE_APPLY	= 301
ID_INSTANCE_UNAPPLY	= 302

class gcb_control( wx.Panel ):
	def __init__( self, parent, id, account ):
		wx.Panel.__init__( self, parent, id )
		self.parent 	= parent
		self.account 	= account
		self.qualifier	= ""
		self.qid		= ""
		self.create_menu_items()
		# Connect a timer to this frame
		self.timer = wx.Timer( self, ID_CGTIMER_TIMER )
		self.Bind( wx.EVT_TIMER, self.OnTimer, id=ID_CGTIMER_TIMER )
		# Create the top bar
		self.topbar = wx.BoxSizer( wx.HORIZONTAL )
		# The new button
		self.new_button = wx.BitmapButton( self, -1, images.getNewBinderBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.new_button.Bind( wx.EVT_BUTTON, self.OnGCBCreate )
		self.topbar.Add( self.new_button, 0 )
		# The refresh button
		self.refresh_button = wx.BitmapButton( self, -1, images.getRefreshBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.refresh_button.Bind( wx.EVT_BUTTON, self.OnRefresh )
		self.topbar.Add( self.refresh_button, 0 )
		# The show selector
		#variables = ['any value', 'header','footer','left','content','right']
		variables = ['','rule','binder','instance']
		self.variable_choice = wx.Choice( self, -1, choices=variables )
		self.variable_choice.SetSelection( 0 )
		self.variable_choice.Bind( wx.EVT_CHOICE, self.OnShowByChange )
		self.topbar.Add( self.variable_choice, 1, wx.EXPAND )
		# the relation button
		self.find_rel_button = wx.BitmapButton( self, -1, images.getContainsBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.find_rel_button.Bind( wx.EVT_BUTTON, self.OnRelChange )
		self.find_rel_button.Enable( False )
		self.topbar.Add( self.find_rel_button, 0 )
		# The find text box
		self.find_text = wx.TextCtrl( self, -1, '', style=wx.TE_PROCESS_ENTER )
		self.find_text.Enable( False )
		self.find_text.Bind( wx.EVT_TEXT, self.OnFindTextKeyPress )
		self.find_text.Bind( wx.EVT_TEXT_ENTER, self.OnRefresh )
		self.topbar.Add( self.find_text, 2, wx.EXPAND )
		# The finding selector
		self.rpp_choice = wx.Choice( self, ID_RPP, choices=["10 per page", "30 per page","50 per page", "100 per page"] )
		self.rpp_choice.SetSelection( 1 )
		self.Bind( wx.EVT_CHOICE, self.OnRPPChange, id=ID_RPP )
		self.topbar.Add( self.rpp_choice, 1, wx.EXPAND )
		#self.find_by = 1	# Find by ID by default
		self.zoom_button = wx.BitmapButton( self, -1, images.getZoomBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.zoom_button.Bind( wx.EVT_BUTTON, self.OnZoom )
		self.topbar.Add( self.zoom_button, 0 )
		# Enable the top bar controls
		self.reset_values()
		#self.enable_topbar( True )
		self.filter_set = False
		# Create the list
		self.list = wx.ListCtrl( self, ID_GCB_LIST, style=wx.LC_REPORT )
		self.il = wx.ImageList(16, 16)
		# Load our images
		#self.gcb_icon		= self.il.Add( images.getGCBBitmap() )
		self.gcb_icon		= self.il.Add( images.getFolderWBitmap() )
		self.list.SetImageList( self.il, wx.IMAGE_LIST_SMALL )
		# Store the default item color
		self.item_color = self.list.GetTextColour()
		self.list.Bind( wx.EVT_LEFT_DCLICK, self.OnItemDoubleClick )
		# default?
		self.list.Bind( wx.EVT_RIGHT_DOWN, self.OnListRightClick )
		# for wxGTK
		#self.list.Bind( wx.EVT_RIGHT_UP, self.OnListRightClick )
		# for wxMSW
		#self.list.Bind( wx.EVT_COMMAND_RIGHT_CLICK, self.OnListRightClick )
		self.Bind( wx.EVT_LIST_ITEM_SELECTED, self.OnItemActivated, id=ID_GCB_LIST )
		self.Bind( wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, id=ID_GCB_LIST )
		#if wx.Platform != '__WXMAC__':
		self.list.Bind( wx.EVT_LIST_BEGIN_DRAG, self.OnBeginDrag )
		# Add it's columns
		info = wx.ListItem()
		info.m_mask = wx.LIST_MASK_TEXT # | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT
		info.m_format = 0
		info.m_text = "ID"
		self.list.InsertColumnInfo(0, info)

		info.m_text = "Rule"
		self.list.InsertColumnInfo(1, info)
		
		info.m_text = "Instances"
		self.list.InsertColumnInfo(2, info)
		
		#info.m_text = "Kind"
		#self.list.InsertColumnInfo(2, info)

		# Resize them all
		self.resize_columns()

		# Create the bottom bar
		self.botbar = wx.BoxSizer( wx.HORIZONTAL )

		# Create prev and next buttons
		self.prev_button = wx.BitmapButton( self, -1, images.getLeftArrowBitmap(), style=wx.NO_BORDER )
		self.prev_button.Bind( wx.EVT_BUTTON, self.GetPrev )
		self.prev_button.Enable( False )
		self.botbar.Add( self.prev_button, 0, wx.EXPAND )
		self.pager = wx.StaticText( self, -1, ' ' )
		self.botbar.Add( self.pager, 1, wx.ALIGN_CENTER )
		self.next_button = wx.BitmapButton( self, -1, images.getRightArrowBitmap(), style=wx.NO_BORDER )
		self.next_button.Bind( wx.EVT_BUTTON, self.GetNext )
		self.botbar.Add( self.next_button, 0, wx.EXPAND )
		self.reset_values()
		# The whole mess
		self.sizer = wx.BoxSizer( wx.VERTICAL )
		self.sizer.Add( self.topbar, 0, wx.EXPAND )
		self.sizer.Add( self.list, 1, wx.EXPAND )
		self.sizer.Add( self.botbar, 0, wx.EXPAND )
		self.SetSizer( self.sizer )
		self.SetAutoLayout( 1 )
		if self.account.window: self.account.window.SetStatusText( "Ready" )
		wx.Yield()
		self.Layout()
		self.Show()
		self.OnRefresh()

	def OnZoom( self, event ):
		if self.account.window: self.account.window.OnZoom( 3 )

	def OnRelChange( self, event ):
		self.filter_dirty = True
		if self.current_rel == '=':
			self.current_rel = '~'
			self.find_rel_button.SetBitmapLabel( images.getContainsBitmap() )
		elif self.current_rel == '~':
			self.current_rel = '!='
			self.find_rel_button.SetBitmapLabel( images.getNotEqualsBitmap() )
		elif self.current_rel == '!=':
			self.current_rel = '!~'
			self.find_rel_button.SetBitmapLabel( images.getNotContainsBitmap() )
		elif self.current_rel == '!~':
			self.current_rel = '='
			self.find_rel_button.SetBitmapLabel( images.getEqualsBitmap() )
		self.find_text.SetFocus()
		self.update_next_prev_buttons()

	def create_menu_items( self ):
		# The binder menu
		menu = wx.Menu()
		menu.Append( ID_GCB_CREATE, "&Create New GCB", " Create a new GCB" )
		self.Bind( wx.EVT_MENU, self.OnGCBCreate, id=ID_GCB_CREATE )
		menu.Append( ID_GCB_EDIT, "&Edit GCB", " Edit the selected GCB" )
		self.Bind( wx.EVT_MENU, self.OnGCBEdit, id=ID_GCB_EDIT )
		menu.Append( ID_GCB_DELETE, "&Delete GCB", " Delete the selected GCB" )
		self.Bind( wx.EVT_MENU, self.OnGCBDelete, id=ID_GCB_DELETE )
		self.menu = menu		
	
	def OnFindTextKeyPress( self, event ):
		self.filter_dirty = True
		self.current_pattern = self.find_text.GetValue()
		self.update_next_prev_buttons()
		common.dprint("current pattern now", self.current_pattern )

	def OnTimer( self, event ):
		self.GetPage()

	def reset_values( self ):
		self.gcbs 			= {}
		self.variable_choice.SetSelection( 0 )
		self.current_variable 	= ''
		self.current_rel		= '~'
		self.current_pattern	= ''
		self.current_max		= 30
		self.current_page		= 0
		self.total_pages		= 0
		self.total_results		= 0
		self.filter_dirty 		= False

	def resize_columns( self ):
		'''Used internally to recalculate the column sizes'''
		# Set the column header sizes
		for i in range( self.list.GetColumnCount() ):
			self.list.SetColumnWidth( i, wx.LIST_AUTOSIZE )

	def OnShowByChange( self, event ):
		variable = self.variable_choice.GetStringSelection()
		variable = variable.strip()
		if variable == self.current_variable: return
		self.filter_dirty = True
		self.current_variable = variable
		self.find_text.Enable( self.current_variable != '' )
		self.find_rel_button.Enable( self.current_variable != '' )
		if self.current_variable != '':
			self.find_text.SetFocus()
		self.update_next_prev_buttons()

	def OnRPPChange( self, event ):
		sel = self.rpp_choice.GetSelection()
		if sel == 0 :
			self.current_max = 10
		elif sel == 1 :
			self.current_max = 30
		elif sel == 2 :
			self.current_max = 50
		elif sel == 3 :
			self.current_max = 100
		else:
			self.current_max = 10
		
	def AppendGCB( self, gcb ):		
		instances = ", ".join( gcb['instances'] )
		x = self.list.InsertImageStringItem( sys.maxint, gcb["id"], self.gcb_icon )
		self.list.SetStringItem( x , 1, gcb["rule"] )
		self.list.SetStringItem( x , 2, gcb["instances"] )
		self.list.SetItemData( x, x )
		return x
		
	def OnRefresh( self, event=None ):
		self.GetPage( True )

	def OnBeginDrag( self, event ):
		gcbs = self.get_selected()
		if len( gcbs ) < 1: return
		data = wx.PyTextDataObject()
		xmlstring = ""
		for gcb in gcbs:
			xmlstring = xmlstring + "<gcb id=\"%s\" instances=\"%s\" rule=\"%s\" />" % \
					( gcb['id'],gcb['instances'], gcb['rule'] )
		data.SetText( xmlstring )
		ds = wx.DropSource( self )
		ds.SetData( data )
		result = ds.DoDragDrop()
		common.dprint( "begindrag:", result )
		if (not self.main):
			# dropped out in the wild
			if result != 5: return
			self.remove_selected()
			
	def GetPage( self, refresh=False ):
		# Set the filter attibs,
		self.list.DeleteAllItems()
		if self.filter_dirty:
			self.gcbs		= {}
			self.filter_dirty	= False
			self.current_page	= 1
		elif refresh:
			try: del self.gcbs[ self.current_page ]
			except: pass
			if self.current_page == 0: self.current_page = 1

		# Update the status bar
		if self.account.window: self.account.window.SetStatusText( "Getting page %s ..." % self.current_page )
		wx.Yield()
		wx.Yield()
		wx.Yield()
		# Do we use the cache or download ?
		try:
			cache = self.gcbs[ self.current_page ]
		except KeyError:
			cache = None

		if cache:
			for gcb in cache:
				gcb['list_index'] = self.AppendGCB( gcb )
		else:
			# Make the call
			cdom = "<gcbs_get2 variable=\"%s\" relation=\"%s\" pattern=\"%s\" max=\"%s\" page=\"%s\" />" % \
					( self.current_variable, self.current_rel, self.current_pattern, self.current_max, self.current_page )
			cur = wx.BusyCursor()
			ress = None
			try:
				xmlstring = self.account.execute( 'base', "gcbs_get2", DOM=cdom )
				xmlstring = common.prepare_xml( xmlstring )
				cdom 	= minidom.parseString( xmlstring )
				ress	= cdom.firstChild
			except:
				if self.account.window: self.account.window.SetStatusText( "Ready" )
			del cur
			if not ress: return
			self.total_pages = 0
			self.total_results = 0
			try:
				self.total_pages 	= int( ress.attributes["pages"].value )
				self.total_results = int( ress.attributes["count"].value )
			except:
				pass
			self.gcbs[ self.current_page ] = []
			cache = self.gcbs[ self.current_page ]
			for sr in ress.getElementsByTagName("gcb"):
				gcb = {}
				try:
					gcb['id']		= sr.attributes["id"].value
					gcb['rule']		= sr.attributes["rule"].value
					gcb['instances']= sr.attributes["instances"].value
				except:
					common.show_error( "failed to parse gcbs [[%s]]" % sr.toxml().encode( 'utf-8' ), False )
				if not gcb: continue
				# Create a list item
				gcb['list_index'] = self.AppendGCB( gcb )
				#self.AppendResult( gcb )
				cache.append( gcb )
			#except Exception:
			#	print "Failed to load account contacts."
		self.resize_columns()
		label = "   Page %s of %s [%s total]   " % (self.current_page, self.total_pages, self.total_results)
		#print "Label ", label
		self.pager.SetLabel( label )
		self.update_next_prev_buttons()
		if self.account.window: self.account.window.SetStatusText( "Ready" )
		wx.Yield()

	def GetNext( self, event ):
		# if self.current_page >= self.total_pages: return
		self.timer.Stop()
		self.current_page = self.current_page + 1
		# override?
		if self.filter_dirty:
			self.gcbs		= {}
			self.filter_dirty	= False
			self.current_page	= 1
		if self.account.window: self.account.window.SetStatusText( "Getting page %s ..." % self.current_page )
		#wx.Yield()
		# Cache exists already?
		try:
			cache = self.gcbs[ self.current_page ]
			self.GetPage()
			return
		except KeyError:
			pass
		self.timer.Start( 700, 1 )

	def GetPrev( self, event ):
		if self.current_page <= 1: return
		self.timer.Stop()
		self.current_page = self.current_page - 1
		if self.account.window: self.account.window.SetStatusText( "Getting page %s ..." % self.current_page )
		#wx.Yield()
		# Cache exists already?
		try:
			cache = self.gcbs[ self.current_page ]
			self.GetPage()
			return
		except KeyError:
			pass
		self.timer.Start( 700, 1 )

	def update_next_prev_buttons( self ):
		#print "Checking np %s, %s" % ( self.current_page, self.total_pages )
		if self.filter_dirty:
			self.next_button.Enable( True )
			self.prev_button.Enable( False )
			return
		#
		if self.current_page >= self.total_pages:
			#print "DISABLING next_button"
			self.next_button.Enable( False )
		else:
			#print "ENABLING next_button"
			self.next_button.Enable( True )

		if self.current_page <= 1:
			#print "DISABLING prev_button"
			self.prev_button.Enable( False )
		else:
			#print "ENABLING prev_button"
			self.prev_button.Enable( True )

	def OnListRightClick( self, event ):
		#try:
		point = event.GetPositionTuple()
		if wx.Platform == '__WXGTK__':
			point = wx.Point( event.m_x + 5, event.m_y + 45 )
		self.PopupMenu( self.menu, point )
		#except:
		#	pass

	def OnItemDoubleClick( self, event ):
		self.OnGCBEdit( event )

	def OnItemActivated( self, event ):
		self.currentItem = event.m_itemIndex

	def get_cache( self ):
		try:
			cache = self.gcbs[ self.current_page ]
		except KeyError:
			self.gcbs[ self.current_page ] = []
			cache = self.gcbs[ self.current_page ]
		return cache

	def get_selected( self ):
		sel = []
		count = self.list.GetItemCount()
		if count < 1: return sel
		for i in range( 0, count ):
			if self.list.IsSelected( i ):
				sel.append( self.gcbs[ self.current_page ][i] )
		return sel

	def OnGCBCreate( self, event ):
		gcb = {}
		# Create, get the new id
		dom = "<gcb id='0' rule='' instances='' />"
		gcb_id = self.account.execute( 'base', 'gcb_save', dom=dom )
		common.dprint("Got id back ", gcb_id )
		gcb['id'] = gcb_id
		gcb['rule'] = ''
		gcb['instances'] = ''
		gcb['list_index'] = self.AppendGCB( gcb )
		self.resize_columns()
		self.list.Select( gcb['list_index'] )
		self.currentItem = gcb['list_index']
		#if self.current_page == 0:
		#		self.current_page = 1
		#		self.gcbs[ self.current_page ] = []
		self.gcbs[ self.current_page ].append( gcb )
		self.OnGCBEdit( None )
	
	def OnGCBEdit( self, event ):
		if self.currentItem is None: return
		gcbIndex = self.list.GetItemData( self.currentItem )
		if gcbIndex < 0: return
		try:
			gcb = self.gcbs[ self.current_page ][ gcbIndex ]
		except KeyError:
			return
		sui = suiGCB( self, gcb, self.currentItem )
		common.metalic( sui )
		sui.Show()
		self.list.Enable( False )
		
	def OnGCBDelete( self, event ):
		sel = common.get_selected_in_list( self.list )
		if len( sel ) < 1: return
		# Confirm delete
		res = wx.MessageBox( "Are you sure you want to delete this GCB?", "Confirm Delete", wx.YES_NO )
		if res != wx.YES: return
		# Create the dom
		gcbids = ""
		for gi in sel:
			gcbIndex = self.list.GetItemData( gi )
			common.dprint(" gcb id ", gcbIndex )
			if gcbIndex < 0: return
			gcb_object = self.gcbs[self.current_page][ gcbIndex ]
			#except KeyError:
			#	common.dprint( self.gcbs )
			#	common.dprint("gcb_object failed")
			#	return
			gcbids = gcbids + "<gcb id=\"" + gcb_object["id"] + "\" />"
		cdom = "<gcbs>%s</gcbs>" % gcbids		
		result = self.account.execute( 'base', "gcbs_delete", DOM=cdom )
		if result:
			self.OnRefresh()
			self.currentItem = -1

#---------------------------------------------------------------------------------------------------
class suiGCB( wx.Dialog ):
	def __init__( self, parent, gcb_object, list_index ):
		title = "GCB - [ %s ]" % gcb_object["id"]
		wx.Dialog.__init__( self, parent, -1, title, wx.DefaultPosition, wx.Size( 350, 300 )  )
		self.account = parent.account
		self.parent  = parent
		self.list_index = list_index
		self.gcb	 = gcb_object
		
		sizer = wx.BoxSizer( wx.VERTICAL )
		sizer.Add( wx.StaticText ( self, -1, "When this group membership rule is satisfied:" ), 0, wx.LEFT | wx.RIGHT, 20 )
		self.rule = wx.TextCtrl( self, ID_RULE, self.gcb["rule"] )
		sizer.Add( self.rule, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 20 )
		sizer.Add( wx.StaticText ( self, -1, "Apply the following instances:" ), 0, wx.LEFT | wx.RIGHT, 20 )
		
		self.list = wx.ListCtrl( self, INS_LIST, style=wx.LC_REPORT )
		sizer.Add( self.list, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 20 )
		info = wx.ListItem()
		info.m_mask = wx.LIST_MASK_TEXT # | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT
		#info.m_image = -1
		info.m_format = 0
		info.m_text = "Instances"
		self.list.InsertColumnInfo(0, info)		
		self.list.Bind( wx.EVT_RIGHT_DOWN, self.OnListRightClick )
		self.Bind( wx.EVT_LIST_ITEM_SELECTED, self.OnItemActivated, id=INS_LIST )
		self.Bind( wx.EVT_LIST_ITEM_ACTIVATED, self.OnItemActivated, id=INS_LIST )
		
		# Set the drop target
		dt = suiGCBDropTarget( self.list, self )
		self.list.SetDropTarget( dt )		
		# Set the drag and drop events
		#if wx.Platform != '__WXMAC__':
		self.list.Bind( wx.EVT_TREE_BEGIN_DRAG, self.OnBeginDrag, id=INS_LIST )

		# Load the current instances
		instances = self.gcb["instances"].split( ', ' )
		for ins in instances:
			self.AppendInstance( ins )
			
		self.resize_columns()
				
		# Add the buttons
		self.button_sizer = wx.BoxSizer( wx.HORIZONTAL )
		btn = wx.Button( self, -1, "&Save" )
		btn.Bind( wx.EVT_BUTTON, self.OnSave )
		self.button_sizer.Add( (0,0) , 0, 1 )
		self.button_sizer.Add( btn, 1, 0 )
		self.button_sizer.Add( (0,0) , 0, 1 )
		btn = wx.Button( self, -1, "&Cancel" )
		btn.Bind( wx.EVT_BUTTON, self.OnClose )
		btn.SetDefault()
		self.button_sizer.Add( btn, 1, 0 )
		self.button_sizer.Add( (0,0) , 0, 1 )

		self.sizer = wx.BoxSizer( wx.VERTICAL )
		self.sizer.Add( sizer, 1, wx.EXPAND | wx.NORTH | wx.SOUTH | wx.EAST | wx.WEST, 10 )
		self.sizer.Add( self.button_sizer, 0, wx.EXPAND | wx.ALIGN_CENTER | wx.SOUTH, 20 )

		self.SetSizer( self.sizer )
		self.SetAutoLayout( 1 )
		# Windows needs this call
		self.Layout()
		# create the instances popup menu and hook up the events
		menu = wx.Menu()
		menu.Append( ID_INSTANCE_APPLY, "&Apply", " Apply the instance from the clipboard" )
		menu.Append( ID_INSTANCE_UNAPPLY, "&UnApply", " Unapply the selected instance" )
		self.menu = menu
		self.Bind( wx.EVT_MENU, self.OnPaste, id=ID_INSTANCE_APPLY )
		self.Bind( wx.EVT_MENU, self.OnCut, id=ID_INSTANCE_UNAPPLY )

	def OnClose( self, event ):
		#~ print "OnClose"
		self.parent.list.Enable( True )
		self.Destroy()
		
	def OnSave( self, event ):
		#~ print "OnSave"
		# Set the rule
		self.gcb["rule"] = self.rule.GetValue()
		if len( self.gcb["rule"] ) < 1: return
		
		# Set the instances
		l = []
		for i in range( 0, self.list.GetItemCount() ):
			ins = self.list.GetItemText( i )
			if l.__contains__( ins ): continue
			l.append( ins )
		self.gcb['instances'] = ", ".join( l )
		
		cur = wx.BusyCursor()
		
		dom = "<gcb id='%s' rule='%s' instances='%s' />" % ( self.gcb["id"], self.gcb["rule"], self.gcb["instances"] )
		gcb_id = self.account.execute( 'base', 'gcb_save', dom=dom )
		common.dprint("Saved, Got id back ", gcb_id )
		if gcb_id > 0:		
			self.parent.list.SetStringItem( self.list_index, 1, self.gcb["rule"] )
			self.parent.list.SetStringItem( self.list_index, 2, self.gcb["instances"] )
			self.parent.list.Enable( True )
			self.parent.resize_columns()
			self.Destroy()
		else:
			common.dprint("Failed to Save GCB")
			# Confirm retry
			wx.MessageBox( "Failed to save GCB, please try again", "Failed to Save GCB", wx.OK )

	def OnBeginDrag( self, event ):
		list = self.list
		sel = get_selected_in_list( list )
		if len( sel ) < 1: return
		
		data = wx.PyTextDataObject("")
		
		ds = wx.DropSource( self )
		ds.SetData( data )
		result = ds.DoDragDrop()
		if result == 5:
			# Remove the object
			try:
				list.DeleteItem( sel[0] )
			except:
				pass
		#~ print self.objects
	
	def AppendInstance( self, ins ):
		x = self.list.GetItemCount()
		if len( ins ) < 1: return
		self.list.InsertStringItem( x, ins )
						
	def resize_columns( self ):
		for i in range( self.list.GetColumnCount() ):
			self.list.SetColumnWidth( i, wx.LIST_AUTOSIZE )

	def OnListRightClick( self, event ):
		common.dprint("Right Click")
		self.PopupMenu( self.menu, wx.Point( event.m_x, event.m_y ) )
		
	def OnPaste( self, event ):
		common.dprint("OnPaste")
		wx.TheClipboard.Open()
		clipdata = wx.TextDataObject()
		wx.TheClipboard.GetData( clipdata )
		wx.TheClipboard.Close()
		data = clipdata.GetText()
		tag = data.replace("[","").replace("]","")
		id_tag = ''
		name_tag = ''
		try:
			id_tag,name_tag = tag.split('|')
		except:
			common.show_error("Failed to parse instance tag")
			return
		if len( id_tag ) < 3:
			common.dprint("Invalid tag data %s" % data )
			return
		self.AppendInstance( id_tag )
		self.resize_columns()
	
	def OnCut( self, event ):
		common.dprint("OnCut")
		list = self.list
		sel = common.get_selected_in_list( list )
		if len( sel ) < 1: return
		try:
			list.DeleteItem( sel[0] )
		except:
			pass

	def OnItemActivated( self, event ):
		common.dprint("OnItemActivated")

class suiGCBDropTarget( wx.PyDropTarget ):
	def __init__( self, list_object, sui ):
		wx.PyDropTarget.__init__( self )
		self.list 	= list_object
		self.sui	= sui
		self.data   = wx.PyTextDataObject()
		self.SetDataObject( self.data )
		
	def OnEnter( self, x, y, d ):
		#print "OnEnter: %d %d %d\n" % (x, y, d)
		return wx.DragCopy
	
	def OnLeave( self ):
		#print "OnLeave"
		pass
	
	def OnDrop( self, x, y ):
		#print "OnDrop: %d %d\n" % ( x, y )
		return True
	
	def OnDragOver( self, x, y, d ):
		return wx.DragCopy
	
	def OnData( self, x, y, d ):
		#~ print "OnData: %d %d %d\n" % (x, y, d)
		if self.GetData():
			data = self.data.GetText()
			tag = data.replace("[","").replace("]","")
			id_tag = ''
			name_tag = ''
			try:
				id_tag,name_tag = tag.split('|')
			except:
				common.show_error("Failed to parse instance tag")
				return
			if len( id_tag ) < 3: return
			# We are applying binder instances
			self.sui.AppendInstance( id_tag )
			self.sui.resize_columns()
			return wx.DragCopy
		else:
			common.dprint( "Failed to get the dnd data" )
		return wx.DragNone
		